<?php
namespace App\Models\System;

use App\Exceptions\ApiException;
use App\Providers\LengthAwarePaginatorProvider;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use App\Enums\System\SysRole\{DataScope, Status, DelFlag};

/**
* 角色信息表 模型
* @create 2023-08-15 23:23:08
*/
class SysRoleModel extends \App\Models\BaseModel {
    use HasFactory;

    const Table         = "sys_role";
    const PrimaryKey    = "role_id";
    public $timestamps  = true;

    static $Wheres = ['role_id', 'data_scope', 'status', 'del_flag'];     // 直接定义column, 默认where(column, '=', value)
    public function __construct($attributes = []) {
        parent::__construct($attributes);

        // static::$Wheres['role_id']   = fn($q, $v) => $q->where(atn('role_id'), '=', $v);
        static::$Wheres['role_name']    = fn($q, $v) => $q->where(atn('role_name'), 'like', "%{$v}%");
        static::$Wheres['role_key']     = fn($q, $v) => $q->where(atn('role_key'), 'like', "%{$v}%");
        static::$Wheres['begin_time']   = fn($q, $v) => $q->whereDate(atn('create_time'), '>=', $v);    // ymd
        static::$Wheres['end_time']     = fn($q, $v) => $q->whereDate(atn('create_time'), '<=', $v);    // ymd
    }


    /** 角色所拥有的部门 */
    public function depts() { return $this->belongsToMany(SysDeptModel::class,SysRoleDeptModel::Table,'role_id','dept_id'); }

    static $Vo = ['role_id','role_name','role_key','role_sort','data_scope','menu_check_strictly','dept_check_strictly','status','del_flag','create_by','create_time','update_by','update_time','remark',];

    public function scopeSelectVo(Builder $query): void {
        // $query->select(atn(static::is_api() ? static::$Voi : static::$Vo, static::Table));
        $query
            ->select(atn(static::$Vo))
            ->distinct()
            ->leftJoin(SysUserRoleModel::Table, SysUserRoleModel::atn('role_id'), '=', atn('role_id'))
            ->leftJoin(SysUserModel::Table, SysUserModel::atn('user_id'), '=', SysUserRoleModel::atn('user_id'))
            ->leftJoin(SysDeptModel::Table, SysDeptModel::atn('dept_id'), '=', SysUserModel::atn('dept_id'))
            ;
     }

    /**
     * 根据条件分页查询角色数据
     * 
     * @param $role 角色信息
     * @return SysRoleModel[]|Collection 角色数据集合信息
     */
    public function selectRoleList(array $role=null): Collection {
        return $this->selectVo()
            ->where(atn('del_flag'), '=', '0')
            ->wheres($role, 'role_id', 'role_name', 'status', 'role_key', 'begin_time', 'end_time')
            ->orderBy(atn('role_sort'))
            ->get()
            ;
    }

    /**
     * 根据用户ID查询角色
     * 
     * @param $userId 用户ID
     * @return SysRoleModel[]|Collection 角色列表
     */
    public function selectRolePermissionByUserId($userId): Collection {
        return $this->selectVo()
            ->where(atn('del_flag'), '=', '0')
            ->where(SysUserRoleModel::atn('user_id'), '=', $userId)
            // ->orderBy(atn('role_sort'))
            ->get()
            ;
    }

    /**
     * 查询所有角色
     * 
     * @return SysRoleModel[] 角色列表
     */
    public function selectRoleAll(): Collection {
        return $this->selectVo()
            // ->where(atn('del_flag'), '=', '0')
            // ->orderBy(atn('role_sort'))
            ->get()
            ;
    }

    /**
     * 根据用户ID获取角色选择框列表
     * 
     * @param $userId 用户ID
     * @return int[] 选中角色ID列表
     */
    public function selectRoleListByUserId($userId): Collection {    // List<Long>
        return $this
            ->select(atn('role_id'))
            ->leftJoin(SysUserRoleModel::Table, SysUserRoleModel::atn('role_id'), '=', atn('role_id'))
            ->leftJoin(SysUserModel::Table, SysUserModel::atn('user_id'), '=', SysUserRoleModel::atn('user_id'))
            ->where(SysUserModel::atn('user_id'), '=', $userId)
            ->get()
            ;
    }

    /**
     * 通过角色ID查询角色
     * 
     * @param $roleId 角色ID
     * @return 角色对象信息
     */
    public function selectRoleById($roleId): SysRoleModel {
        return throw_str(
            $this->selectVo()
                ->where(atn('role_id'), '=', $roleId)
                ->first() 
            ?? "角色($roleId)查找失败");
    }

    /**
     * 根据用户ID查询角色
     * 
     * @param $userName 用户名
     * @return SysRoleModel[] 角色列表
     */
    public function selectRolesByUserName($userName): Collection {
        return $this->selectVo()
            ->where(atn('del_flag'), '=', '0')
            ->where(SysUserModel::atn('user_name'), '=', $userName)
            // ->orderBy(atn('role_sort'))
            ->get()
            ;
    }

    /**
     * 校验角色名称是否唯一
     * 
     * @param $roleName 角色名称
     * @return 角色信息
     */
    public function checkRoleNameUnique($roleName): SysRoleModel {
        return $this->selectVo()
            ->where(atn('del_flag'), '=', '0')
            ->where(atn('role_name'), '=', $roleName)
            // ->orderBy(atn('role_sort'))
            ->limit(1)
            ->first()
            ;
    }

    /**
     * 校验角色权限是否唯一
     * 
     * @param $roleKey 角色权限
     * @return 角色信息
     */
    public function checkRoleKeyUnique($roleKey): SysRoleModel {
        return $this->selectVo()
            ->where(atn('del_flag'), '=', '0')
            ->where(atn('role_key'), '=', $roleKey)
            // ->orderBy(atn('role_sort'))
            ->limit(1)
            ->first()
            ;
    }

    /**
     * 修改角色信息
     * 
     * @param $role 角色信息
     * @return 结果
     */
    public function updateRole(array $role): int {
        $values = static::when(
                    $role,
                    'role_name',
                    'role_key',
                    'role_sort',
                    'data_scope',
                    'menu_check_strictly',
                    'dept_check_strictly',
                    'status',
                    'remark',
                    'update_by',
                );
        return $this
                ->where(atn('role_id'), '=', get_value($role, 'role_id'))
                ->update($values);
    }

    /**
     * 新增角色信息
     * 
     * @param $role 角色信息
     * @return 结果
     */
    public function insertRole(array $role): SysRoleModel {
        $values = static::when(
                    $role,
                    'role_id',
                    'role_name',
                    'role_key',
                    'role_sort',
                    'data_scope',
                    'menu_check_strictly',
                    'dept_check_strictly',
                    'status',
                    'remark',
                    'create_by',
                );
        return throw_str(
            static::row_add($values)
        );
    }

    /**
     * 通过角色ID删除角色
     * 
     * @param $roleId 角色ID
     * @return 结果
     */
    public function deleteRoleById($roleId): int {
        return $this->deleteRoleByIds($roleId);
    }

    /**
     * 批量删除角色信息
     * 
     * @param $roleIds 需要删除的角色ID
     */
    public function deleteRoleByIds($roleIds): int {
        return $this
                ->whereIn('role_id', explode(',', $roleIds))
                ->update(['del_flag' => 2])
                ;
    }

    /** ========== 常用查询 ========== */
    static $Voi = ['*', ];

    /** 根据RoleId获取 */
    public function selectByRoleId($role_id): SysRoleModel {
        $where = [['role_id', '=', "{$role_id}"]];
        return throw_str(
            static::row($where) ?? "数据($role_id)为空~"
        );
    }


    /** 获取列表 @return SysRole[]+paginator() */
    public function selectList(int|array $pag=1, array $param=[]): LengthAwarePaginatorProvider {
        return static::rows_pag($pag, [], fn($q)=>$q
                    // ->when(isset($param['role_id']), fn($q)=>$q->where('role_id', '=', $param['role_id']))
                    ->wheres($param, 'role_id','data_scope','status','del_flag')
                    ->orderByDesc("role_id")
        );
    }


    /** 插入数据 */
    public function insertData(array $data): SysRoleModel {
        return throw_str(
            static::row_add([
                // 'role_id'            => $data['role_id'],
                'role_name'             => $data['role_name'],
                'role_key'              => $data['role_key'],
                'role_sort'             => $data['role_sort'],
                'data_scope'            => $data['data_scope'] ?? '1',
                'menu_check_strictly'   => $data['menu_check_strictly'] ?? '1',
                'dept_check_strictly'   => $data['dept_check_strictly'] ?? '1',
                'status'                => $data['status'],
                'del_flag'              => $data['del_flag'] ?? '0',
                'create_by'             => $data['create_by'] ?? '',
                // 'create_time'        => $data['create_time'] ?? '',
                'update_by'             => $data['update_by'] ?? '',
                // 'update_time'        => $data['update_time'] ?? '',
                'remark'                => $data['remark'] ?? '',
            ])
        );
    }


    /** 更新数据 */
    public function updateData(int|array $idOrWhere, array $data): SysRoleModel {
        $values = static::when(
                    $data, 
                    // 'role_id',
                    'role_name',
                    'role_key',
                    'role_sort',
                    'data_scope',
                    'menu_check_strictly',
                    'dept_check_strictly',
                    'status',
                    'del_flag',
                    'create_by',
                    // 'create_time',
                    'update_by',
                    // 'update_time',
                    'remark',
                );
        return throw_str(
            static::row_update($idOrWhere, $values)
        );
    }


    /** 删除数据 */
    public function deleteData(int|array $idOrWhere): SysRoleModel {
        return throw_str(
            static::row_delete($idOrWhere)
        );
    }



}